/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.repair.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.cache.DictCache;
import org.springblade.common.config.ProjectApiConfiguration;
import org.springblade.common.constant.BaseRoleConstant;
import org.springblade.common.constant.MaintenanceSmsConstant;
import org.springblade.common.constant.TemplateMsgConstant;
import org.springblade.common.constant.VoiceConstant;
import org.springblade.common.utils.AsyncHttpUtil;
import org.springblade.common.utils.RobotUtil;
import org.springblade.common.utils.mq.MqMessageService;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseEntity;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.node.ForestNodeMerger;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.modules.notice.annotation.MsgNotice;
import org.springblade.modules.notice.core.Process;
import org.springblade.modules.notice.core.event.NoticeEvent;
import org.springblade.modules.notice.dto.NoticeTaskParam;
import org.springblade.modules.notice.enums.BusinessType;
import org.springblade.modules.notice.enums.TriggerConditionEnum;
import org.springblade.modules.notice.enums.TriggerNodeEnum;
import org.springblade.modules.repair.dto.PlanLogDTO;
import org.springblade.modules.repair.dto.RobotContentDTO;
import org.springblade.modules.repair.dto.TicketFeedBackDTO;
import org.springblade.modules.repair.entity.*;
import org.springblade.modules.repair.enums.*;
import org.springblade.modules.repair.mapper.MaintainMalfunctionWorkMapper;
import org.springblade.modules.repair.service.*;
import org.springblade.modules.repair.service.approve.strategy.ApproveBusinessFlow;
import org.springblade.modules.repair.service.approve.strategy.ApproveBusinessStrategy;
import org.springblade.modules.repair.utils.DateUtils;
import org.springblade.modules.repair.utils.MapUtil;
import org.springblade.modules.repair.vo.*;
import org.springblade.modules.repair.vo.part.SearchPartsTreeVo;
import org.springblade.modules.repair.vo.plan.PlanPartStatusVo;
import org.springblade.modules.repair.vo.plan.wx.PlanMaintainUserVO;
import org.springblade.modules.repair.vo.plan.wx.WxUserPlanVo;
import org.springblade.modules.repair.vo.plan.wx.WxYjSendMsgVo;
import org.springblade.modules.resource.utils.SmsUtil;
import org.springblade.modules.system.entity.Tenant;
import org.springblade.modules.system.entity.TenantConfig;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.*;
import org.springblade.modules.system.vo.SimpleUserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 故障工单明细 服务实现类
 *
 * @author zcc
 * @since 2021-05-22
 */
@Service
@Slf4j
public class MaintainMalfunctionWorkServiceImpl extends BaseServiceImpl<MaintainMalfunctionWorkMapper, MaintainMalfunctionWork> implements IMaintainMalfunctionWorkService {

	@Autowired
	private IMaintainSignService signService;
	@Autowired
	private IMaintainMalfunctionHistoryService malfunctionHistoryService;

	@Autowired
	@Lazy
	private IMaintainMalfunctionWorkService malfunctionWorkService;

	@Autowired
	private IMaintainMalfunctionLogService maintainMalfunctionLogService;

	@Resource
	private IMaintainPlanContentService maintainPlanContentService;

	@Autowired
	private IMaintainPlanContentUserService maintainPlanContentUserService;

	@Autowired
	private IMaintainPlanContentExtService maintainPlanContentExtService;

	@Autowired
	@Lazy
	private IMaintainMalfunctionLogService malfunctionLogService;

	@Autowired
	private IElevatorService elevatorService;

	@Autowired
	private IElevatorPlanStatusService elevatorPlanStatusService;

	@Autowired
	private BladeRedis bladeRedis;

	@Autowired
	private IUserService userService;

	@Autowired
	private ITenantService tenantService;

	@Resource
	private WeChatDialogueService weChatDialogueService;

	@Autowired
	private IMaintainPlanRelationService planRelationService;

	@Autowired
	private ProjectApiConfiguration projectApiConfiguration;

	@Autowired
	private AsyncHttpUtil asyncHttpUtil;
	@Autowired
	private RobotUtil robotUtil;

	@Autowired
	private MaintainPartsService maintainPartsService;

	@Autowired
	@Lazy
	private MaintainPartsWorkService maintainPartsWorkService;

	@Autowired
	@Lazy
	private IMaintainPlanCheckService maintainPlanCheckService;

	@Autowired
	@Lazy
	private IMaintainPlanRelationService maintainPlanRelationService;

	@Autowired
	private MqMessageService mqMessageService;

	@Autowired
	private IElevatorStopLogService elevatorStopLogService;
	@Lazy
	@Autowired
	private MaintainReportService reportService;


	@Value("${part.api.url}")
	private String part_search_url;

	@Autowired
	private IMaintainWxmsgTypeService maintainWxmsgTypeService;


	/**
	 * 新增报障前缀key
	 */
	private static final String malWorkPrefix = "MAL_WORK_SAVE_";

	@Autowired
	private IUserTrajectoryService userTrajectoryService;

	@Autowired
	private IBuildingExtService buildingExtService;

	@Autowired
	private UserExtService userExtService;

	@Autowired
	private TenantConfigService tenantConfigService;

	@Autowired
	private IBuildingService buildingService;

	@Resource
	private ApplicationEventPublisher eventPublisher;

	@Autowired
	private IElevatorRepeatFaultConfigService elevatorRepeatFaultConfigService;

	@Autowired
	private IRoleService roleService;

	@Autowired
	private IWxFaultCauseService wxFaultCauseService;

	@Autowired
	private IRescueNoticeService rescueNoticeService;

	@Override
	public IPage<MaintainMalfunctionWorkVO> selectMaintainMalfunctionWorkPage(IPage<MaintainMalfunctionWorkVO> page, MaintainMalfunctionWorkVO maintainMalfunctionWork) {
		return page.setRecords(baseMapper.selectMaintainMalfunctionWorkPage(page, maintainMalfunctionWork));
	}

	@Override
	public MalfunctionWorkDetailVo detailByPlanId(Long planId, Long userId) {

		MalfunctionWorkDetailVo result = new MalfunctionWorkDetailVo();
		result.setMaintainMalfunctionWork(baseMapper.detailByPlanId(planId, userId));
		MaintainPlanContent maintainPlanContent = maintainPlanContentService.getById(planId);
		if (maintainPlanContent.getStatus() == MaintainPlanContentStatusEnum.DISABLE.getId()) {
			return result;
		}
		return result;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public HashMap<String, Object> malfunctionWorkSave(RepairWorkVO repairWorkVO) {

		//计算维修达到时间
		Long buildingId = elevatorService.getById(repairWorkVO.getElevatorId()).getBuildingId();
		BuildingExt buildingExt = buildingExtService.getOne(Wrappers.<BuildingExt>lambdaQuery().eq(BuildingExt::getBuildingId, buildingId));
		if (StrUtil.isNotEmpty(buildingExt.getMalfunctionWorkArrivalTime())) {
			//预计达到时间
			long timeMillis = System.currentTimeMillis();
			if (buildingExt.getMalfunctionWorkArrivalTime().contains("m")) {
				Long time = Convert.toLong(buildingExt.getMalfunctionWorkArrivalTime().replace("m", "")) * 60 * 1000;
				timeMillis = timeMillis + time;
				Date date2 = new Date(timeMillis);
				repairWorkVO.setPlanArriveDate(date2);
			} else if (buildingExt.getMalfunctionWorkArrivalTime().contains("h")) {
				Long time = Convert.toLong(buildingExt.getMalfunctionWorkArrivalTime().replace("h", "")) * 60 * 60 * 1000;
				timeMillis = timeMillis + time;
				Date date2 = new Date(timeMillis);
				repairWorkVO.setPlanArriveDate(date2);
			}
		}
		HashMap<String, Object> resultMap = new HashMap<>(2);

		User user = userService.getById(AuthUtil.getUserId());

		boolean planSaveFlag = false;
		MaintainPlanContent maintainPlanContent = new MaintainPlanContent();
		// redis根据电梯id + 用户id + 状态作为key值
		String key = malWorkPrefix + repairWorkVO.getElevatorId() + repairWorkVO.getUserIds() + repairWorkVO.getTypeStatus();
		//如果不存在key则保存报障工单
		if (!bladeRedis.exists(key)) {
			bladeRedis.setEx(key, UUID.randomUUID().toString(), Duration.ofSeconds(10L));
			maintainPlanContent.setElevatorId(repairWorkVO.getElevatorId());
			maintainPlanContent.setPlanDate(DateUtil.date());
			maintainPlanContent.setTypeStatus(repairWorkVO.getTypeStatus());
			maintainPlanContent.setPlanFinishDate(repairWorkVO.getPlanFinishDate());
			// 2024-04-25 新增 来源工单类型
			maintainPlanContent.setSourcePlanType(repairWorkVO.getSourcePlanType());
			planSaveFlag = maintainPlanContentService.save(maintainPlanContent);

			if (ObjectUtil.isNotEmpty(repairWorkVO.getFromPlanId())) {
				MaintainPlanRelation planRelation = new MaintainPlanRelation();
				planRelation.setFromPlanId(repairWorkVO.getFromPlanId());
				planRelation.setOwnPlanId(maintainPlanContent.getId());
				planRelationService.save(planRelation);
			}
		} else {
			throw new ServiceException("10秒内，请勿重复提交报障信息！");
		}

		if (planSaveFlag) {
			if (Func.isNotEmpty(repairWorkVO.getWorks())) {
				repairWorkVO.getWorks().forEach(e -> {
					e.setPlanId(maintainPlanContent.getId());
				});
				super.saveBatch(repairWorkVO.getWorks());

				//更新关系
				List<Long> mailIds = repairWorkVO.getWorks().stream().map(MaintainMalfunctionWork::getMalHistoryId).collect(Collectors.toList());
				List<MaintainMalfunctionHistory> maintainMalfunctionHistories = malfunctionHistoryService.listByIds(mailIds);
				maintainMalfunctionHistories.forEach(o -> o.setChildPlanId(maintainPlanContent.getId()));
				malfunctionHistoryService.updateBatchById(maintainMalfunctionHistories);

				//更新质检工单的子工单数量
				if (repairWorkVO.getFromPlanId() != null) {
					MaintainPlanCheck maintainPlanCheck = maintainPlanCheckService.getOne(Wrappers.<MaintainPlanCheck>lambdaQuery().eq(MaintainPlanCheck::getPlanId, repairWorkVO.getFromPlanId()));
					if (maintainPlanCheck != null) {
						Integer childCounts = Convert.toInt(maintainPlanCheck.getChildCounts(), 0);
						maintainPlanCheck.setChildCounts(childCounts + 1);
						maintainPlanCheckService.updateById(maintainPlanCheck);
					}
				}
			}
			// 2024-04-28 新增来源工单关联关系
			if (!Func.isNull(repairWorkVO.getFromPlanId())) {
				MaintainPlanRelation maintainPlanRelation = new MaintainPlanRelation();
				maintainPlanRelation.setFromPlanId(repairWorkVO.getFromPlanId());
				maintainPlanRelation.setOwnPlanId(maintainPlanContent.getId());
			}
			ApproveBusinessFlow flowStrategy = ApproveBusinessStrategy.get(ApproveTypeEnum.MALFUNCTION_APPLY.getId());
			BusinessApproveVO businessApprove = new BusinessApproveVO();
			businessApprove.setName("维修报障");
			businessApprove.setType(ApproveTypeEnum.MALFUNCTION_APPLY.getId());
			businessApprove.setSubmitId(AuthUtil.getUserId());
			businessApprove.setSubmitName(AuthUtil.getUserName());
			businessApprove.setApproveIds(repairWorkVO.getParentUserIds().stream().collect(Collectors.joining(",")));
			//添加审批信息
			List<User> users = userService.listByIds(repairWorkVO.getParentUserIds());
			List<String> userNames = users.stream().map(User::getRealName).collect(Collectors.toList());
			businessApprove.setApproveName(userNames.stream().collect(Collectors.joining(",")));
			businessApprove.setWorkOrderId(maintainPlanContent.getId());
			businessApprove.setPhone(user.getPhone());
			businessApprove.setApproveStatus(ApproveStatusEnum.PENDING.getId());
			if (repairWorkVO.getUserIds() != null && repairWorkVO.getUserIds().size() > 0) {
				businessApprove.setApproveStatus(ApproveStatusEnum.PASSED.getId());
			}
			businessApprove.setAssignUsers(repairWorkVO.getUserIds());

			MaintainPlanContentExt maintainPlanContentExt = new MaintainPlanContentExt();
			maintainPlanContentExt.setPlanId(maintainPlanContent.getId());
			maintainPlanContentExt.setElevatorStop(repairWorkVO.getElevatorStop());
			maintainPlanContentExt.setEmerProcType(repairWorkVO.getEmerProcType());
			maintainPlanContentExt.setWorkOrderType(repairWorkVO.getWorkOrderType());
			maintainPlanContentExt.setFaultCompany(tenantService.getOne(Wrappers.<Tenant>lambdaQuery().eq(Tenant::getTenantId, user.getTenantId())).getTenantName());

			// 维修工单事件等级
			if (Func.isNotEmpty(maintainPlanContent.getElevatorId())) {
				ElevatorRepeatFaultConfig faultConfig = elevatorRepeatFaultConfigService.getFaultLevelByElevator(maintainPlanContent.getElevatorId());
				if (Func.isNotEmpty(faultConfig)) {
					maintainPlanContentExt.setFaultLabel(faultConfig.getTypeDesc());
					maintainPlanContentExt.setFaultLevel(faultConfig.getLevel());
					maintainPlanContentExt.setFaultOvertime(faultConfig.getOvertimeDay());
				}
			}
			maintainPlanContentExtService.save(maintainPlanContentExt);

			flowStrategy.addApprove(businessApprove);

			resultMap.put("planId", maintainPlanContent.getId());
			resultMap.put("businessApproveId", businessApprove.getId());
			if ("592800".equals(AuthUtil.getTenantId())) {
				asyncHttpUtil.createPost(projectApiConfiguration.getWeb() + "/admin/lark/galaxy/elevator/repair/plan", Func.toJson(maintainPlanContent), WebUtil.getRequest());
			}

			// 发送停梯延预警通知
			if (repairWorkVO.getElevatorStop().equals(ElevatorStatusEnum.STOP.getStatus())) {
//				long sendTime = DateUtil.date().getTime() + 5*60*1000;
//				long sendTime = DateUtil.date().getTime() + 60 * 60 * 1000;
//				JSONObject msg = new JSONObject();
//				msg.put("msgType", 1);
//				msg.put("contentType", 1);
//				msg.put("planId", maintainPlanContent.getId());
//				msg.put("elevatorId", maintainPlanContent.getElevatorId());
//				mqMessageService.sendElevatorStopMsg(sendTime, JSONObject.toJSONString(msg));

				// 推送通知
				List<Integer> triggerConditions = new ArrayList<>();
				// 停梯1小时预警通知
//				triggerConditions.add(TriggerConditionEnum.CONDITION_6.getCode());
				// 停梯2小时预警通知
				triggerConditions.add(TriggerConditionEnum.CONDITION_7.getCode());
				// 停梯4小时预警通知
//				triggerConditions.add(TriggerConditionEnum.CONDITION_8.getCode());
				Map<String, Object> callback = new HashMap<>();
				callback.put("elevatorId", repairWorkVO.getElevatorId());
				callback.put("msgCode", TriggerConditionEnum.CONDITION_7.getCode());
				for (Integer triggerCondition : triggerConditions) {
					eventPublisher.publishEvent(new NoticeEvent(NoticeTaskParam.builder()
						.businessType(BusinessType.REPAIR.getCode())
						.triggerNode(TriggerNodeEnum.CREATE.getCode())
						.triggerCondition(triggerCondition)
						.bizId(maintainPlanContent.getId())
						.tenantId(AuthUtil.getTenantId())
						.callback(callback)
						.build()
					));
				}
			}

			Elevator elevator = elevatorService.getById(maintainPlanContent.getElevatorId());
			if (ObjectUtil.isNotEmpty(elevator) && ObjectUtil.isNotEmpty(elevator.getIsStop())) {
				if (!elevator.getIsStop().equals(repairWorkVO.getElevatorStop())) {
					ElevatorStopLog elevatorStopLog = new ElevatorStopLog();
					elevatorStopLog.setElevatorId(maintainPlanContent.getElevatorId());
					elevatorStopLog.setInitStatus(elevator.getIsStop());
					elevatorStopLog.setSetStatus(repairWorkVO.getElevatorStop());
					elevatorStopLog.setModule(String.valueOf(maintainPlanContent.getId()));
					elevatorStopLog.setPosition(3);
					elevatorStopLogService.insertStopLog(elevatorStopLog);

					elevator.setIsStop(repairWorkVO.getElevatorStop());
					elevatorService.updateById(elevator);
				}
			}
			// 2025-07 当新增维修工单成功后，更新告警信息
			Long rescueNoticeId = repairWorkVO.getRescueNoticeId();
			if(Func.isNotEmpty(rescueNoticeId)){
				RescueNotice currentRescueNotice = rescueNoticeService.getById(rescueNoticeId);
				if(!currentRescueNotice.getConfirmType().equals(RescueNoticeConfirmTypeEnum.NOT_CONFIRM.getConfirmType())){
					throw new ServiceException("报警已经确认，无需再确认");
				}
				currentRescueNotice.setPlanId(maintainPlanContent.getId());
				rescueNoticeService.updateById(currentRescueNotice);
				TicketFeedBackDTO feedBack = new TicketFeedBackDTO();
				feedBack.setDeviceId(currentRescueNotice.getDeviceId());
				feedBack.setRescueId(currentRescueNotice.getCallId());
				feedBack.setIsCreateRescue(false);
				feedBack.setState(1);
				asyncHttpUtil.createPost(projectApiConfiguration.getWeb() + "/admin/rescue/notice/feedback", Func.toJson(feedBack), WebUtil.getRequest());
			}
			return resultMap;
		}

		return null;
	}

	@Override
	public MalFunctionDetailVO selectMalfunctionDetail(Long planId) {
		return baseMapper.selectMalfunctionDetail(planId);
	}

	@Override
	public MalFunctionDetailVO malfunctionDetail(Long planId) {

		Map<Long, List<WxFaultCause>> wxFaultCauseMap = wxFaultCauseService.list().stream().collect(Collectors.groupingBy(WxFaultCause::getId));

		MaintainPlanContent planContent = maintainPlanContentService.getById(planId);


		// 查询维修详情
		MalFunctionDetailVO malFunctionDetailVO = this.selectMalfunctionDetail(planId);
		// 2024-04-28 新增计划时间、预计完成时间、来源类型、来源类型名
		malFunctionDetailVO.setPlanFinishDate(planContent.getPlanFinishDate());
		malFunctionDetailVO.setPlanDate(planContent.getPlanDate());
		if (!Func.isNull(planContent.getSourcePlanType())) {
			String sourcePlanTypeName = MaintainPlanContentEnum.getName(planContent.getSourcePlanType());
			malFunctionDetailVO.setSourcePlanTypeName(sourcePlanTypeName);
			malFunctionDetailVO.setSourcePlanType(planContent.getSourcePlanType());
		}
		if (Func.isNotEmpty(malFunctionDetailVO.getFaultMessageList())) {
			malFunctionDetailVO.getFaultMessageList().forEach(e -> {
				// 封装故障现象信息
				if (StringUtil.isNotBlank(e.getProblemItem())) {
					List<String> problemKeys = Func.toStrList(e.getProblemItem());
					List<String> problemNames = new ArrayList<>();
					for (String problemKey : problemKeys) {
						String problemName = DictCache.getValue("fault_problem", problemKey);
						problemNames.add(problemName);
					}
					e.setProblemItemNames(problemNames);
				}
				if (StringUtil.isNotBlank(e.getFaultReasonItem())) {
					List<String> faultReasonKeys = Func.toStrList(e.getFaultReasonItem());
					List<String> faultReasonItemNames = new ArrayList<>();
					for (String faultReasonKey : faultReasonKeys) {
						final List<WxFaultCause> wxFaultCauses = wxFaultCauseMap.get(Convert.toLong(faultReasonKey));
						if (wxFaultCauses != null && wxFaultCauses.size() > 0) {
							faultReasonItemNames.add(wxFaultCauses.get(0).getFaultName());
						}
					}
					e.setFaultReasonItemNames(faultReasonItemNames);
				}
				// 2024-04-26 封装user_name
				if (!Func.isNull(e.getCreateUserId())) {
					User createUser = userService.getById(e.getCreateUserId());
					e.setCreateUserName(createUser.getRealName());
				}
			});
		}

		// 查询该任务电梯最近一次完成的任务
		LastPlanVO lastPlanVO = maintainPlanContentService.selectElevatorLastPlan(malFunctionDetailVO.getElevatorId(), planId);
		malFunctionDetailVO.setLastPlan(lastPlanVO);

		// 查询维修操作记录
		List<MalFunctionHistoryVO> malFunctionHistories = malfunctionHistoryService.selectByPlanId(planId);
		List<Long> ids = malFunctionHistories.stream().map(MalFunctionHistoryVO::getId).collect(Collectors.toList());
		if (ids.size() > 0) {
			List<MaintainPartsWork> maintainPartsWorks = maintainPartsWorkService.getMaintainPartsWorkListOfMalId(ids);
			Map<Long, List<MaintainPartsWork>> listMap = maintainPartsWorks.stream().collect(Collectors.groupingBy(MaintainPartsWork::getMalPartId));
			for (MalFunctionHistoryVO malFunctionHistoryVO : malFunctionHistories) {
				List<MaintainPartsWork> partsWorks = listMap.get(malFunctionHistoryVO.getId());
				if (partsWorks == null || partsWorks.size() == 0) {
					continue;
				}
				malFunctionHistoryVO.setMaintainPartsWorks(partsWorks);
			}
		}

		malFunctionDetailVO.setMalFunctionHistories(malFunctionHistories);

		// 查询关联人员信息
		List<MaintainPlanContentUser> planContentUsers = maintainPlanContentUserService.list(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId, planId));
		if (ObjectUtil.isNotEmpty(planContentUsers)) {
			planContentUsers = planContentUsers.stream().filter(e -> {
				String userName = userService.getById(e.getUserId()).getRealName();
				e.setUserName(userName);
				Integer userSignCount = signService.count(Wrappers.<MaintainSign>lambdaQuery().eq(MaintainSign::getPlanId, e.getPlanId()).eq(MaintainSign::getUserId, e.getUserId()));
				e.setUserSignCount(userSignCount);
				if (planContent.getStatus().equals(TaskStatusEnum.WX_SIGN_FINISH.getStatus())) {
					int signCount = signService.count(Wrappers.<MaintainSign>lambdaQuery().eq(MaintainSign::getPlanId, planId).eq(MaintainSign::getUserId, e.getUserId()));
					if (signCount > 0) {
						return true;
					}
				} else {
					return true;
				}
				return false;
			}).collect(Collectors.toList());
			malFunctionDetailVO.setPlanContentUsers(planContentUsers);
		}

		malFunctionDetailVO.setUpdateStatus(Boolean.TRUE);
		// 完成工单后24小时内可以上传检修记录
		if (malFunctionDetailVO.getStatus().equals(TaskStatusEnum.WX_SIGN_FINISH.getStatus())) {
			MaintainPlanContentExt planContentExt = maintainPlanContentExtService.getOne(Wrappers.<MaintainPlanContentExt>lambdaQuery().eq(MaintainPlanContentExt::getPlanId, planId));
			long betweenHour = DateUtil.between(planContentExt.getPlanEndTime(), DateUtil.date(), DateUnit.HOUR);
			if (betweenHour > 24) {
				malFunctionDetailVO.setUpdateStatus(Boolean.FALSE);
			}
		}

		// 获取当天本人同一台梯是否存在签到记录的签到图片
		ElevatorLastPlanVO lastSignImg = signService.selectUserLastSignImgByElevator(AuthUtil.getUserId(), planContent.getElevatorId());
		malFunctionDetailVO.setLastSignImg(lastSignImg);

		// 统计关联未完成的部件更换
		int correlationPlan = maintainPlanContentService.countCorrelationPlan(planId);
		malFunctionDetailVO.setPartsCount(correlationPlan);

		List<MaintainReport> reportList = reportService.list(Wrappers.<MaintainReport>lambdaQuery().eq(MaintainReport::getPlanId, planId).orderByDesc(MaintainReport::getCreateTime).last("limit 1"));
		if (Func.isNotEmpty(reportList)) {
			malFunctionDetailVO.setReportId(reportList.get(0).getId());
		}
		return malFunctionDetailVO;
	}

	@Override
	public MalFunctionApproveDetailVO malfunctionApproveDetail(Long planId) {

		MaintainPlanContent planContent = maintainPlanContentService.getById(planId);

		// 查询维修审核详情
		MalFunctionApproveDetailVO malFunctionApproveDetailVO = baseMapper.selectMalfunctionApproveDetail(planId);

		if (Func.isNotEmpty(malFunctionApproveDetailVO.getFaultMessageList())) {
			malFunctionApproveDetailVO.getFaultMessageList().forEach(e -> {
				// 封装故障现象信息
				if (StringUtil.isNotBlank(e.getProblemItem())) {
					List<String> problemKeys = Func.toStrList(e.getProblemItem());
					List<String> problemNames = new ArrayList<>();
					for (String problemKey : problemKeys) {
						String problemName = DictCache.getValue("fault_problem", problemKey);
						problemNames.add(problemName);
					}
					e.setProblemItemNames(problemNames);
				}
				if (StringUtil.isNotBlank(e.getProblemItem())) {
					List<String> problemKeys = Func.toStrList(e.getProblemItem());
					List<String> problemNames = new ArrayList<>();
					for (String problemKey : problemKeys) {
						String problemName = DictCache.getValue("fault_problem", problemKey);
						problemNames.add(problemName);
					}
					e.setProblemItemNames(problemNames);
				}
			});
		}

		// 查询关联人员信息
		List<MaintainPlanContentUser> planContentUsers = maintainPlanContentUserService.list(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId, planId));
		if (ObjectUtil.isNotEmpty(planContentUsers)) {
			planContentUsers = planContentUsers.stream().filter(e -> {
				String userName = userService.getById(e.getUserId()).getRealName();
				e.setUserName(userName);
				Integer userSignCount = signService.count(Wrappers.<MaintainSign>lambdaQuery().eq(MaintainSign::getPlanId, e.getPlanId()).eq(MaintainSign::getUserId, e.getUserId()));
				e.setUserSignCount(userSignCount);
				if (planContent.getStatus().equals(TaskStatusEnum.WX_SIGN_FINISH.getStatus())) {
					int signCount = signService.count(Wrappers.<MaintainSign>lambdaQuery().eq(MaintainSign::getPlanId, planId).eq(MaintainSign::getUserId, e.getUserId()));
					if (signCount > 0) {
						return true;
					}
				} else {
					return true;
				}
				return false;
			}).collect(Collectors.toList());
			malFunctionApproveDetailVO.setPlanContentUsers(planContentUsers);
		}

		FaultFeedbackVO faultFeedbackVO = baseMapper.selectMalfunctionApprove(planId);
		malFunctionApproveDetailVO.setFaultFeedbackVO(faultFeedbackVO);

		return malFunctionApproveDetailVO;
	}

	@Override
	public List<MalfunctionPartsTreeVO> selectMalPartsTree(String keyWord) {
		List<MalfunctionPartsTreeVO> malfunctionPartsTreeVOS = baseMapper.selectMalPartsTree(null);
		if (Func.isNotEmpty(malfunctionPartsTreeVOS)) {
			malfunctionPartsTreeVOS = ForestNodeMerger.merge(malfunctionPartsTreeVOS);
		}
		if (StrUtil.isEmpty(keyWord)) {
			return malfunctionPartsTreeVOS;
		} else {
			List<MalfunctionPartsTreeVO> oneChild = new ArrayList<>(16);
			for (MalfunctionPartsTreeVO malfunctionPartsTreeVO : malfunctionPartsTreeVOS) {
				List<MalfunctionPartsTreeVO> children = malfunctionPartsTreeVO.getChildren();
				List<MalfunctionPartsTreeVO> towChild = new ArrayList<>(16);
				for (MalfunctionPartsTreeVO malfunctionPartsTreeVO1 : children) {
					List<MalfunctionPartsTreeVO> children1 = malfunctionPartsTreeVO1.getChildren();
					//第三级如果包括关键字就添加到第三级数组
					List<MalfunctionPartsTreeVO> threeChild = new ArrayList<>(16);
					for (MalfunctionPartsTreeVO malfunctionPartsTreeVO2 : children1) {
						if (malfunctionPartsTreeVO2.getName().contains(keyWord)) {
							threeChild.add(malfunctionPartsTreeVO2);
						}
					}

					//如果第三级数组大于0就设置到第二级的数组
					if (threeChild.size() > 0) {
						malfunctionPartsTreeVO1.setChildren(threeChild);
						towChild.add(malfunctionPartsTreeVO1);
					}
				}
				//如果第二级数组大于0就设置到第一级的数组
				if (towChild.size() > 0) {
					malfunctionPartsTreeVO.setChildren(towChild);
					oneChild.add(malfunctionPartsTreeVO);
				}

			}
			return oneChild;
		}
	}

	@Override
	public List<SearchPartsTreeVo> selectMalPartsTreeV2(String keyWord) {

		List<SearchPartsTreeVo> resultList = new ArrayList<>(50);
		if (StrUtil.isEmpty(keyWord)) {
			return resultList;
		}

		//下次迭代的需求
//		String responseBody = HttpUtil.get(part_search_url + "/api/es-search/listByTitle?title=" + keyWord);
//		JSONArray jsonArray = JSON.parseArray(responseBody);
//		List<Long> partIds = new ArrayList<>(16);
//		for (int i = 0; i < jsonArray.size(); i++) {
//			String string = jsonArray.get(i).toString();
//			partIds.add(Convert.toLong(JSON.parseObject(string).get("id")));
//		}
		List<MaintainParts> partsList = maintainPartsService.list();
		Map<Long, List<MaintainParts>> listMap = partsList.stream().collect(Collectors.groupingBy(MaintainParts::getId));

		//
		List<MalfunctionPartsTreeVO> malfunctionPartsTreeVOS = baseMapper.selectMalPartsTree(keyWord);


		List<MalfunctionPartsTreeVO> newList = new ArrayList<>();

		//只要最小级别的
		for (MalfunctionPartsTreeVO malfunctionPartsTreeVO : malfunctionPartsTreeVOS) {
			if (malfunctionPartsTreeVO.getChildren().size() == 0) {
				newList.add(malfunctionPartsTreeVO);
			}
		}
		//根据最小级别获取上级
		for (MalfunctionPartsTreeVO malfunctionPartsTreeVO : newList) {
			SearchPartsTreeVo searchPartsTreeVo = new SearchPartsTreeVo();
			List<MaintainParts> maintainParts = recursionPart(malfunctionPartsTreeVO.getParentId(), listMap, new ArrayList<>());
			maintainParts.add(listMap.get(malfunctionPartsTreeVO.getId()).get(0));
			maintainParts.sort(Comparator.comparing(MaintainParts::getLevel));
			List<String> names = maintainParts.stream().map(MaintainParts::getName).collect(Collectors.toList());
			List<Long> ids = maintainParts.stream().map(MaintainParts::getId).collect(Collectors.toList());
			searchPartsTreeVo.setIds(ids);
			searchPartsTreeVo.setNames(names);
			resultList.add(searchPartsTreeVo);
		}

		return resultList;
	}


	@Override
	public PlanPartStatusVo getPartListCounts(Long planId) {
		return baseMapper.getPartListCounts(planId);
	}

	@Override
	public Boolean updateMalDetail(MaintainMalfunctionWork malfunctionWork) {
		MaintainMalfunctionWork entity = super.getOne(Wrappers.<MaintainMalfunctionWork>lambdaQuery().eq(MaintainMalfunctionWork::getPlanId, malfunctionWork.getPlanId()));
		if (ObjectUtil.isEmpty(entity)) {
			throw new ServiceException("工单详情数据异常");
		}
		entity.setElevatorStop(malfunctionWork.getElevatorStop());
		entity.setProblemItem(malfunctionWork.getProblemItem());
		entity.setProblemOtherDesc(malfunctionWork.getProblemOtherDesc());
		return super.updateById(entity);
	}

	@Override
	public String getPreTime(Long id) {
		// 数据库中获取预计完成时间
		Date time = maintainPlanContentService.getById(id).getFinishDate();
//		String result = null;
		if (Func.isNull(time)) {
			return null;
		}
//		// 判断预计完成时间是否在近三天内
//		Calendar calendar = Calendar.getInstance();
//		calendar.add(Calendar.DAY_OF_MONTH, 3);
//		Date threeDaysLater = calendar.getTime();
//		if (time.before(threeDaysLater)) {
//			// 预计完成时间在近三天内
//			Date today = new Date();
//			Date tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000);
//			Date theNextDay = new Date(tomorrow.getTime() + 24 * 60 * 60 * 1000);
//			Date theNextTwoDay = new Date(theNextDay.getTime() + 24 * 60 * 60 * 1000);
//			// 判断预计完成时间是今天还是明天
//			if (time.before(tomorrow)) {
//				// 预计完成时间是今天
//				SimpleDateFormat todayFormat = new SimpleDateFormat("yyyy-MM-dd '(今天)' HH:mm");
//				result = "预计维修结束时间" + todayFormat.format(time);
//			} else if(time.after(tomorrow) && time.before(theNextDay)) {
//				// 预计完成时间是明天
//				SimpleDateFormat tomorrowFormat = new SimpleDateFormat("yyyy-MM-dd '(明天)' HH:mm");
//				result = "预计维修结束时间" + tomorrowFormat.format(time);
//			} else if(time.after(theNextDay) &&  time.before(theNextTwoDay)){
//				// 预计完成时间是后天
//				SimpleDateFormat theNextDayFormat = new SimpleDateFormat("yyyy-MM-dd '(后天)' HH:mm");
//				result = "预计维修结束时间" + theNextDayFormat.format(time);
//			}
//		} else {
//			// 预计完成时间不在近三天内
//			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
//			result = "预计维修结束时间" + dateFormat.format(time);
//		}

		return time.toString();
	}

	@Override
	public FaultFeedbackVO getFeedbackMessage(Long id) {
		return baseMapper.getFeedbackMessage(id);
	}

	@Override
	public Integer getApproveStatus(Long id) {
		return baseMapper.getApproveStatus(id);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean malfunctionWorkUpdateMessage(RepairWorkVO repairWorkVO) {
		// 1. 必传参数校验
		Long planId = repairWorkVO.getPlanId();
		if (Func.isNull(planId)) {
			throw new ServiceException("Please send plan id !");
		}
		MaintainPlanContent maintainPlanContent = maintainPlanContentService.getById(planId);
		if (Func.isNull(maintainPlanContent) || Func.isNull(maintainPlanContent.getIsDeleted())) {
			throw new ServiceException("Fail! This plan is not exist or this plan is deleted!");
		}

		// 2024-04-24 新增字段
		if (!Func.isNull(repairWorkVO.getSourcePlanType())) {
			List<Long> fromPlanIds = maintainPlanContentService.getFromPlanIdByOwnId(planId);
			if (Func.isNotEmpty(fromPlanIds)) {
				Integer sourcePlanType = maintainPlanContent.getSourcePlanType();
				if (!repairWorkVO.getSourcePlanType().equals(sourcePlanType)) {
					throw new ServiceException("该工单已有关联工单来源，无法修改");
				}
			} else {
				maintainPlanContent.setSourcePlanType(repairWorkVO.getSourcePlanType());
			}
		} else {
			maintainPlanContent.setSourcePlanType(null);
		}

		// 2. 更新主表
		maintainPlanContent.setElevatorId(repairWorkVO.getElevatorId());
		maintainPlanContent.setPlanDate(DateUtil.date());
		maintainPlanContent.setTypeStatus(repairWorkVO.getTypeStatus());

		LambdaUpdateWrapper<MaintainPlanContent> updateWrapper = new LambdaUpdateWrapper<MaintainPlanContent>();
		updateWrapper.eq(MaintainPlanContent::getId, planId);
		updateWrapper.set(MaintainPlanContent::getElevatorId, maintainPlanContent.getElevatorId())
			.set(MaintainPlanContent::getTypeStatus, maintainPlanContent.getTypeStatus())
			.set(MaintainPlanContent::getProcessDefinitionId, maintainPlanContent.getProcessDefinitionId())
			.set(MaintainPlanContent::getProcessInstanceId, maintainPlanContent.getProcessInstanceId())
			.set(MaintainPlanContent::getPlanDate, maintainPlanContent.getPlanDate())
			.set(MaintainPlanContent::getFinishDate, maintainPlanContent.getFinishDate())
			.set(MaintainPlanContent::getIsDeferred, maintainPlanContent.getIsDeferred())
			.set(MaintainPlanContent::getPlanFrom, maintainPlanContent.getPlanFrom())
			.set(MaintainPlanContent::getSourcePlanType, maintainPlanContent.getSourcePlanType())
			.set(MaintainPlanContent::getPlanFinishDate, maintainPlanContent.getPlanFinishDate());
		boolean main = maintainPlanContentService.update(updateWrapper);

		// 拓展表
		MaintainPlanContentExt maintainPlanContentExt = maintainPlanContentExtService.getOne(new LambdaQueryWrapper<MaintainPlanContentExt>()
			.eq(MaintainPlanContentExt::getPlanId, planId)
			.eq(BaseEntity::getIsDeleted, 0)
		);
		maintainPlanContentExt.setElevatorStop(repairWorkVO.getElevatorStop());
		maintainPlanContentExt.setEmerProcType(repairWorkVO.getEmerProcType());
		maintainPlanContentExt.setWorkOrderType(repairWorkVO.getWorkOrderType());
		maintainPlanContentExtService.updateById(maintainPlanContentExt);

		// 维修详情
		if (Func.isEmpty(repairWorkVO.getWorks())) {
			throw new ServiceException("维修报障信息不可为空");
		}
		repairWorkVO.getWorks().forEach(e -> {
			e.setPlanId(repairWorkVO.getPlanId());
		});
		malfunctionWorkService.remove(Wrappers.<MaintainMalfunctionWork>lambdaQuery().eq(MaintainMalfunctionWork::getPlanId, repairWorkVO.getPlanId()));
		boolean detail = malfunctionWorkService.saveBatch(repairWorkVO.getWorks());

		// 发送停梯延时队列 一小时后
		if (repairWorkVO.getElevatorStop().equals(ElevatorStatusEnum.STOP.getStatus())) {
			// 推送通知
			List<Integer> triggerConditions = new ArrayList<>();
			// 停梯1小时预警通知
//				triggerConditions.add(TriggerConditionEnum.CONDITION_6.getCode());
			// 停梯2小时预警通知
			triggerConditions.add(TriggerConditionEnum.CONDITION_7.getCode());
			// 停梯4小时预警通知
//				triggerConditions.add(TriggerConditionEnum.CONDITION_8.getCode());
			Map<String, Object> callback = new HashMap<>();
			callback.put("elevatorId", repairWorkVO.getElevatorId());
			callback.put("msgCode", TriggerConditionEnum.CONDITION_7.getCode());
			for (Integer triggerCondition : triggerConditions) {
				eventPublisher.publishEvent(new NoticeEvent(NoticeTaskParam.builder()
					.businessType(BusinessType.REPAIR.getCode())
					.triggerNode(TriggerNodeEnum.CREATE.getCode())
					.triggerCondition(triggerCondition)
					.bizId(planId)
					.tenantId(AuthUtil.getTenantId())
					.callback(callback)
					.build()
				));
			}
		}


		//计算维修达到时间
		Long buildingId = elevatorService.getById(repairWorkVO.getElevatorId()).getBuildingId();
		BuildingExt buildingExt = buildingExtService.getOne(Wrappers.<BuildingExt>lambdaQuery().eq(BuildingExt::getBuildingId, buildingId));
		if (StrUtil.isNotEmpty(buildingExt.getMalfunctionWorkArrivalTime())) {
			//预计达到时间
			long timeMillis = System.currentTimeMillis();
			if (buildingExt.getMalfunctionWorkArrivalTime().contains("m")) {
				Long time = Convert.toLong(buildingExt.getMalfunctionWorkArrivalTime().replace("m", "")) * 60 * 1000;
				timeMillis = timeMillis + time;
				Date date2 = new Date(timeMillis);
				repairWorkVO.setPlanArriveDate(date2);
			} else if (buildingExt.getMalfunctionWorkArrivalTime().contains("h")) {
				Long time = Convert.toLong(buildingExt.getMalfunctionWorkArrivalTime().replace("h", "")) * 60 * 60 * 1000;
				timeMillis = timeMillis + time;
				Date date2 = new Date(timeMillis);
				repairWorkVO.setPlanArriveDate(date2);
			}
		}

		this.sendYjMsg(repairWorkVO, maintainPlanContent.getId());

		Elevator elevator = elevatorService.getById(maintainPlanContent.getElevatorId());
		if (ObjectUtil.isNotEmpty(elevator) && ObjectUtil.isNotEmpty(elevator.getIsStop())) {
			if (!elevator.getIsStop().equals(repairWorkVO.getElevatorStop())) {
				ElevatorStopLog elevatorStopLog = new ElevatorStopLog();
				elevatorStopLog.setElevatorId(maintainPlanContent.getElevatorId());
				elevatorStopLog.setInitStatus(elevator.getIsStop());
				elevatorStopLog.setSetStatus(repairWorkVO.getElevatorStop());
				elevatorStopLog.setModule(String.valueOf(maintainPlanContent.getId()));
				elevatorStopLog.setPosition(3);
				elevatorStopLogService.insertStopLog(elevatorStopLog);

				elevator.setIsStop(repairWorkVO.getElevatorStop());
				elevatorService.updateById(elevator);
			}
		}

		return main && detail;
	}

	@Override
	public Long submitMalDetail(MaintainMalfunctionWork malfunctionWork) {
		if (Func.isEmpty(malfunctionWork.getId())) {
			LambdaQueryWrapper<MaintainMalfunctionWork> wrapper = Wrappers.<MaintainMalfunctionWork>lambdaQuery()
				.eq(MaintainMalfunctionWork::getPlanId, malfunctionWork.getPlanId())
				.eq(MaintainMalfunctionWork::getPartsNames, malfunctionWork.getPartsNames())
				.eq(MaintainMalfunctionWork::getPartsIds, malfunctionWork.getPartsIds());
			if (Func.isNotBlank(malfunctionWork.getFloorStandIds())) {
				wrapper.eq(MaintainMalfunctionWork::getFloorStandIds, malfunctionWork.getFloorStandIds())
					.eq(MaintainMalfunctionWork::getFloorStandNames, malfunctionWork.getFloorStandNames());
			}
			long count = super.count(wrapper);
			if (count > 0) {
				throw new ServiceException("不可重复添加故障配件信息");
			}
		}
		super.saveOrUpdate(malfunctionWork);

		MaintainPlanContentExt planContentExt = maintainPlanContentExtService.getOne(Wrappers.<MaintainPlanContentExt>lambdaQuery().eq(MaintainPlanContentExt::getPlanId, malfunctionWork.getPlanId()));
		if (planContentExt.getMalfunctionType() != null) {
			List<String> allList = new ArrayList<>(16);
			List<String> list = Func.toStrList(planContentExt.getMalfunctionType());
			allList.addAll(list);
			if (StrUtil.isNotEmpty(malfunctionWork.getFaultReasonItem())) {
				List<String> list2 = Func.toStrList(malfunctionWork.getFaultReasonItem());
				allList.addAll(list2);
			}
			allList = allList.stream().distinct().collect(Collectors.toList());
			planContentExt.setMalfunctionType(String.join(",", allList));
		} else {
			planContentExt.setMalfunctionType(malfunctionWork.getFaultReasonItem());
		}
		planContentExt.setMalfunctionTypeDesc(malfunctionWork.getFaultReasonOtherDesc());
		maintainPlanContentExtService.updateById(planContentExt);

		return malfunctionWork.getId();
	}

	@Override
	public List<MaintainPlanContent> getPartList(Long planId) {
		return baseMapper.getPartList(planId);
	}

	@Override
	public List<MaintainMalfunctionWork> listByPlanId(Long planId) {
		return baseMapper.listByPlanId(planId);
	}

	@Override
	public List<WxUserPlanVo> userPlanListOfToday(String buildingIds) {
		List<WxUserPlanVo> list = baseMapper.userPlanListOfToday(DateUtil.offsetDay(new Date(), -7), DateUtil.endOfDay(new Date()), AuthUtil.getUserId());
		if (StrUtil.isNotEmpty(buildingIds)) {
			List<Long> ids = new ArrayList<>(16);
			String[] split = buildingIds.split(",");
			for (int i = 0; i < split.length; i++) {
				ids.add(Convert.toLong(split[i]));
			}
			list = list.stream().filter(o -> ids.contains(o.getBuildingId())).collect(Collectors.toList());
		}
		Map<Long, List<WxUserPlanVo>> listMap = list.stream().collect(Collectors.groupingBy(WxUserPlanVo::getBuildingId));
		for (WxUserPlanVo userPlanVo : list) {
			int size = listMap.get(userPlanVo.getBuildingId()).size();
			userPlanVo.setBuildingPlanCounts(size);

			if (userPlanVo.getSignTime() == null) {
				userPlanVo.setSignType(1);
			} else if ((userPlanVo.getSignTime() != null && userPlanVo.getSignOutTime() == null)) {
				userPlanVo.setSignType(2);
			} else if ((userPlanVo.getSignTime() != null && userPlanVo.getSignOutTime() != null)) {
				userPlanVo.setSignType(1);
			}
		}
		return list;
	}

	@Override
	public void sendYjMsg(RepairWorkVO repairWorkVO, Long planId) {
		//预计达到时间
		Date date2 = repairWorkVO.getPlanArriveDate();

		//如果没有分配人员不处理
		if (repairWorkVO.getUserIds() == null || repairWorkVO.getUserIds().size() == 0) {
			return;
		}

		//需求1:当人员指派10分钟后移动不超过500米-发送延迟
		MaintainWxmsgType detail = maintainWxmsgTypeService.detail(AuthUtil.getTenantId());
		if (detail == null || detail.getMoveTime() == null) {
			return;
		}
		long sendTime = DateUtil.date().getTime() + detail.getMoveTime() * 60000;
		JSONObject msg = new JSONObject();
		msg.put("contentType", MaintainPlanContentEnum.MAINTAIN_WX.getId());
		WxYjSendMsgVo wxYjSendMsgVo = new WxYjSendMsgVo();
		wxYjSendMsgVo.setType(1);
		wxYjSendMsgVo.setPlanArriveDate(date2);
		wxYjSendMsgVo.setPlanId(planId);
		List<Long> userIds = repairWorkVO.getUserIds();
		List<PlanMaintainUserVO> maintainUserList = new ArrayList<>(16);
		for (Long maintainUserId : userIds) {
			PlanMaintainUserVO planMaintainUserVO = new PlanMaintainUserVO();
			planMaintainUserVO.setMaintainUserId(maintainUserId);
			UserTrajectory userTrajectory = userTrajectoryService.getOne(Wrappers.<UserTrajectory>lambdaQuery().between(UserTrajectory::getCreateTime, DateUtil.beginOfDay(new Date()), new Date()).eq(UserTrajectory::getUserId, maintainUserId).orderByDesc(UserTrajectory::getCreateTime).last("limit 1"));
			if (userTrajectory != null) {
				planMaintainUserVO.setLongitude(userTrajectory.getLongitude());
				planMaintainUserVO.setLatitude(userTrajectory.getLatitude());

				//计算每个用户的实际达到时间
				UserExt userExt = userExtService.getOne(Wrappers.<UserExt>lambdaQuery().eq(UserExt::getUserId, planMaintainUserVO.getMaintainUserId()));
				if (StrUtil.isNotEmpty(userExt.getVehicle())) {
					TenantConfig tenantConfig = tenantConfigService.getTenantConfig(AuthUtil.getTenantId());
					RescueScreenConfig rescueScreenConfig = tenantConfig.getRescueScreenConfig();
					Building building = buildingService.getById(repairWorkVO.getBuildingId());
					MaintainPlanContentUser planContentUser = maintainPlanContentUserService.getOne(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getUserId, planMaintainUserVO.getMaintainUserId()).eq(MaintainPlanContentUser::getPlanId, planId));
					//交通工具 1-自行车，2-摩托车，3-电动车，4-汽车，5-公交车，6-其它
					try {
						Integer distance = MapUtil.getDistance(MapUtil.getLongitude(userTrajectory.getLongitude()), MapUtil.getLongitude(userTrajectory.getLatitude()), MapUtil.getLongitude(building.getLongitude().toString()), MapUtil.getLongitude(building.getLatitude().toString()));
						BigDecimal multiply;
						if (userExt.getVehicle().equals("1")) {
							multiply = Convert.toBigDecimal(rescueScreenConfig.getBicycle()).multiply(Convert.toBigDecimal(1000));
						} else if (userExt.getVehicle().equals("2")) {
							multiply = Convert.toBigDecimal(rescueScreenConfig.getMotorcycle()).multiply(Convert.toBigDecimal(1000));
						} else if (userExt.getVehicle().equals("3")) {
							multiply = Convert.toBigDecimal(rescueScreenConfig.getElectricVehicle()).multiply(Convert.toBigDecimal(1000));
						} else if (userExt.getVehicle().equals("4")) {
							multiply = Convert.toBigDecimal(rescueScreenConfig.getCar()).multiply(Convert.toBigDecimal(1000));
						} else if (userExt.getVehicle().equals("5")) {
							multiply = Convert.toBigDecimal(rescueScreenConfig.getBus()).multiply(Convert.toBigDecimal(1000));
						} else {
							multiply = Convert.toBigDecimal(rescueScreenConfig.getOther()).multiply(Convert.toBigDecimal(1000));
						}
						BigDecimal divide = Convert.toBigDecimal(distance).divide(multiply.divide(Convert.toBigDecimal(60), 2, BigDecimal.ROUND_HALF_UP), 0, BigDecimal.ROUND_HALF_UP);
						planContentUser.setRealityPlanDate(new Date(DateUtils.getNowDateEnd(DateUtil.offsetMinute(new Date(), Convert.toInt(divide)))));
						planContentUser.setDistance(distance);
					} catch (Exception e) {
						e.printStackTrace();
					}
					maintainPlanContentUserService.updateById(planContentUser);
				}
			}
			maintainUserList.add(planMaintainUserVO);
		}
		List<PlanMaintainUserVO> userVOList = maintainUserList.stream().filter(o -> o.getLatitude() != null).collect(Collectors.toList());
		if (userVOList.size() > 0) {
			wxYjSendMsgVo.setMaintainUserList(userVOList);
			msg.put("wx_yj_msg", wxYjSendMsgVo);
			mqMessageService.sendWxWarnMsg(DateUtils.getNowDateEnd(new Date(sendTime)), JSONObject.toJSONString(msg));
		}

		//需求2：当人员预计到达时长剩余至项目要求到达时长的30%时，APP唤起手机语音提示“XX分后即将超时到达
		//预计达到时间
		if (repairWorkVO.getPlanArriveDate() == null) {
			return;
		}
		Date date1 = new Date();
		long between = DateUtil.between(date1, date2, DateUnit.SECOND);

		//发送超时未达的延迟队列
		WxYjSendMsgVo wxYjSendMsgVo2 = new WxYjSendMsgVo();
		wxYjSendMsgVo2.setType(3);
		wxYjSendMsgVo2.setPlanId(planId);
		wxYjSendMsgVo2.setMaintainUserList(maintainUserList);
		wxYjSendMsgVo2.setPlanArriveDate(date2);
		msg.put("wx_yj_msg", wxYjSendMsgVo2);
		mqMessageService.sendWxWarnMsg(DateUtils.getNowDateEnd(date2), JSONObject.toJSONString(msg));
		//发送即将超时的延迟队列
		//计算百分之30
		BigDecimal divide = Convert.toBigDecimal(detail.getAboutTimeoutRatio()).divide(Convert.toBigDecimal(100));
		between = Convert.toLong(Convert.toBigDecimal(between).multiply(divide));
		DateTime dateTime = DateUtil.offsetSecond(date1, Convert.toInt(between));
		WxYjSendMsgVo wxYjSendMsgVo3 = new WxYjSendMsgVo();
		wxYjSendMsgVo3.setType(2);
		wxYjSendMsgVo3.setPlanId(planId);
		wxYjSendMsgVo3.setPlanArriveDate(date2);
		wxYjSendMsgVo3.setMaintainUserList(maintainUserList);
		msg.put("wx_yj_msg", wxYjSendMsgVo3);
		mqMessageService.sendWxWarnMsg(DateUtils.getNowDateEnd(dateTime), JSONObject.toJSONString(msg));

		log.info("当人员指派10分钟后移动不超过500监听时间:" + DateUtil.format(new Date(sendTime), "yyyy-MM-dd HH:mm:ss"));
		log.info("超时未达的时间:" + DateUtil.format(new Date(date2.getTime()), "yyyy-MM-dd HH:mm:ss"));
		log.info("百分之30时间:" + DateUtil.format(new Date(dateTime.getTime()), "yyyy-MM-dd HH:mm:ss"));
	}

	@MsgNotice(businessType = BusinessType.REPAIR, node = TriggerNodeEnum.FINISH, parameterName = "entity.planId")
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean malfunctionFinish(MaintainMalfunctionWork entity) {
		MaintainPlanContent planContent = maintainPlanContentService.getById(entity.getPlanId());
		if (!planContent.getStatus().equals(TaskStatusEnum.WX_UNDER_WAY.getStatus())) {
			throw new ServiceException("任务状态已变更，请刷新重试！");
		}
		int correlationPlan = maintainPlanContentService.countCorrelationPlan(entity.getPlanId());
		if (correlationPlan > 0) {
			throw new ServiceException("还有配件更换工单未完成，请先查看相关配件工单。");
		}

		// 系统代签 任务提交时 未签退人员自动签退
		signService.checkUserSignOut(entity.getPlanId());

		List<MaintainMalfunctionWork> malfunctionWorkList = malfunctionWorkService.list(Wrappers.<MaintainMalfunctionWork>lambdaQuery().eq(MaintainMalfunctionWork::getPlanId, entity.getPlanId()).orderByAsc(MaintainMalfunctionWork::getId));
		MaintainMalfunctionWork malfunctionWork = malfunctionWorkList.get(0);
//		malfunctionWork.setFaultDesc(entity.getFaultDesc());
//		malfunctionWork.setFaultReasonItem(entity.getFaultReasonItem());
//		malfunctionWork.setFaultReasonOtherDesc(entity.getFaultReasonOtherDesc());
//		malfunctionWorkService.updateById(malfunctionWork);

		// 统计人员上传图片总数
		List<MaintainPlanContentUser> planUsers = maintainPlanContentUserService.list(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId, entity.getPlanId()));
		planUsers.forEach(e -> {
			List<MaintainMalfunctionHistory> malfunctionHistories = malfunctionHistoryService.listByPlanUser(entity.getPlanId(), e.getUserId());
			int userImgNum = 0;
			if (ObjectUtil.isNotEmpty(malfunctionHistories)) {
				userImgNum = malfunctionHistories.stream().filter(j -> ObjectUtil.isNotEmpty(j.getDisposeImgUrl())).map(j -> j.getDisposeImgUrl().stream().filter(k -> "image".equals(k.get("type"))).count()).mapToInt(Long::intValue).sum();
			}
			e.setImageNum(userImgNum);
		});
		maintainPlanContentUserService.updateBatchById(planUsers);

		// 更新工单状态
		planContent.setStatus(TaskStatusEnum.WX_SIGN_FINISH.getStatus());
		maintainPlanContentService.update(planContent);

		// 更新电梯状态
		elevatorService.update(Wrappers.<Elevator>lambdaUpdate().set(Elevator::getIsStop, ElevatorStatusEnum.NORMAL.getStatus()).eq(Elevator::getId, planContent.getElevatorId()));

		// 插入工单记录
		maintainMalfunctionLogService.insertWorkLog(entity.getPlanId(), TaskStatusEnum.getTaskName(planContent.getTypeStatus(), planContent.getStatus()), planContent.getStatus());

		// 处理计划人与实际执行人
		maintainPlanContentUserService.changePlanUser(entity.getPlanId());

		// 发送微信模板消息推送
		// 维修人员名单
//		String planUserName = maintainPlanContentUserService.getPlanUserName(entity.getPlanId());
//		ElevatorSimpleInfoVO elevatorInfo = maintainPlanContentService.getElevatorSimpleInfo(entity.getPlanId());

//		malfunctionWorkList.forEach(e -> {
//			// 封装故障现象信息
//			String faultProblemNames = "";
//			if (StringUtil.isNotBlank(e.getProblemItem())) {
//				List<String> problemKeys = Func.toStrList(e.getProblemItem());
//				List<String> problemNames = new ArrayList<>();
//				for (String problemKey : problemKeys) {
//					String problemName = DictCache.getValue("fault_problem", problemKey);
//					problemNames.add(problemName);
//				}
//				faultProblemNames = problemNames.stream().map(String::valueOf).collect(Collectors.joining("、"));
//			}
//			faultProblemNames = StringUtil.isNotBlank(faultProblemNames) ? faultProblemNames : e.getPartsNames().replace("&amp;&amp;", "-");
//			log.info("给报障人发送模板消息,报障人:[{}], [{}]", e.getName(), "已完成");
//			Map<String, String> processedTemplateDataMap = new HashMap<>(8);
//			processedTemplateDataMap.put("first", "您提交的电梯故障 【维修完成】");
//			processedTemplateDataMap.put("keyword1", elevatorInfo.getBuildingName() + "-" + elevatorInfo.getElevatorAddress());
//			processedTemplateDataMap.put("keyword2", StringUtil.isNotBlank(faultProblemNames) ? faultProblemNames : e.getPartsNames());
//			processedTemplateDataMap.put("keyword3", planUserName);
//			processedTemplateDataMap.put("keyword4", DateUtil.now());
//			processedTemplateDataMap.put("remark", "查看详情");
//			String openId;
//			if (e.getPlanFrom().equals(PlanContentFormTypeEnum.BUILDING.getId())) {
//				openId = userService.getEstateOpenIdByPhone(e.getPhone());
//				if (ObjectUtil.isNotEmpty(openId)) {
//					HashMap<String, Object> map = new HashMap<>(3);
//					map.put("openid", openId);
//					map.put("params", processedTemplateDataMap);
//					map.put("templateId", TemplateMsgConstant.T_REPAIR_FINISH_ID_TO_ESTATE);
//					asyncHttpUtil.createPost(projectApiConfiguration.getEstate() + "/tlw/alarm/official/accounts/push", JSONObject.toJSONString(map));
//				}
//			} else {
//				openId = userService.getOpenIdByPhone(e.getPhone());
//				if (ObjectUtil.isNotEmpty(openId)) {
//					weChatDialogueService.sendMsg(openId, TemplateMsgConstant.T_REPAIR_FINISH_ID, processedTemplateDataMap);
//				}
//			}
//
//			log.info("===========给报障人发送手机短信,报障人:[{}], 手机号码:[{}]===========", e.getName(), e.getPhone());
//			Map<String, String> smsParam = new HashMap<>(2);
//			smsParam.put("auditStatus", "已完成");
//			SmsUtil.sendMessage(MaintenanceSmsConstant.MAINTENANCE_STATUS, BladeConstant.ADMIN_TENANT_ID, smsParam, e.getPhone());
//		});

		// 封装故障现象信息
//		String faultProblemNames = "";
//		if (StringUtil.isNotBlank(malfunctionWork.getProblemItem())) {
//			List<String> problemKeys = Func.toStrList(malfunctionWork.getProblemItem());
//			List<String> problemNames = new ArrayList<>();
//			for (String problemKey : problemKeys) {
//				String problemName = DictCache.getValue("fault_problem", problemKey);
//				problemNames.add(problemName);
//			}
//			faultProblemNames = problemNames.stream().map(String::valueOf).collect(Collectors.joining("、"));
//		}
//		faultProblemNames = StringUtil.isNotBlank(faultProblemNames) ? faultProblemNames : malfunctionWork.getPartsNames().replace("&amp;&amp;", "-");
//		log.info("给报障人发送模板消息,报障人:[{}], [{}]", malfunctionWork.getName(), "已完成");
//		Map<String, String> processedTemplateDataMap = new HashMap<>(8);
//		processedTemplateDataMap.put("first", "您提交的电梯故障 【维修完成】");
//		processedTemplateDataMap.put("keyword1", elevatorInfo.getBuildingName() + "-" + elevatorInfo.getElevatorAddress());
//		processedTemplateDataMap.put("keyword2", StringUtil.isNotBlank(faultProblemNames) ? faultProblemNames : malfunctionWork.getPartsNames());
//		processedTemplateDataMap.put("keyword3", planUserName);
//		processedTemplateDataMap.put("keyword4", DateUtil.now());
//		processedTemplateDataMap.put("remark", "查看详情");
//		String openId;
//		if (malfunctionWork.getPlanFrom().equals(PlanContentFormTypeEnum.BUILDING.getId())) {
//			openId = userService.getEstateOpenIdByPhone(malfunctionWork.getPhone());
//			if (ObjectUtil.isNotEmpty(openId)) {
//				HashMap<String, Object> map = new HashMap<>(3);
//				map.put("openid", openId);
//				map.put("params", processedTemplateDataMap);
//				map.put("templateId", TemplateMsgConstant.T_REPAIR_FINISH_ID_TO_ESTATE);
//				asyncHttpUtil.createPost(projectApiConfiguration.getEstate() + "/tlw/alarm/official/accounts/push", JSONObject.toJSONString(map));
//			}
//		} else {
//			openId = userService.getOpenIdByPhone(malfunctionWork.getPhone());
//			if (ObjectUtil.isNotEmpty(openId)) {
//				weChatDialogueService.sendMsg(openId, TemplateMsgConstant.T_REPAIR_FINISH_ID, processedTemplateDataMap);
//			}
//		}
//
//		log.info("===========给报障人发送手机短信,报障人:[{}], 手机号码:[{}]===========", malfunctionWork.getName(), malfunctionWork.getPhone());
//		Map<String, String> smsParam = new HashMap<>(2);
//		smsParam.put("auditStatus", "已完成");
//		SmsUtil.sendMessage(MaintenanceSmsConstant.MAINTENANCE_STATUS, BladeConstant.ADMIN_TENANT_ID, smsParam, malfunctionWork.getPhone());

		ElevatorDetailVO elevatorDetailVO = elevatorService.selectElevatorDetail(planContent.getElevatorId());
		List<MaintainPlanContentUser> planContentUsers = maintainPlanContentUserService.listUserByPlan(planContent.getId());
		List<String> userName = planContentUsers.stream().map(MaintainPlanContentUser::getUserName).collect(Collectors.toList());

		malfunctionWorkList = malfunctionWorkList.stream().filter(e -> Func.isNotBlank(e.getFaultReasonItem())).collect(Collectors.toList());
		if (Func.isNotEmpty(malfunctionWorkList)) {
			malfunctionWork = malfunctionWorkList.get(0);
		}
		// 机器人消息内容
		RobotContentDTO robotContentDTO = new RobotContentDTO();
		robotContentDTO.setMaintainType(MaintainPlanContentEnum.MAINTAIN_WX.getId());
		robotContentDTO.setMaintainSubTypeDesc("【维修完成通知】");
		StringBuilder locationDesc = new StringBuilder();
		locationDesc.append(elevatorDetailVO.getBuildingName()).append("-").append(elevatorDetailVO.getElevatorAddress());
		robotContentDTO.setLocationDesc(locationDesc.toString());
		robotContentDTO.setMaintainStatusDesc(TaskStatusEnum.WX_SIGN_FINISH.getName());
		robotContentDTO.setElevatorStatusDesc(ElevatorStatusEnum.getName(elevatorDetailVO.getIsStop()));
		robotContentDTO.setMaintainPersonDesc(String.join(",", userName));
		robotContentDTO.setMaintainTimeDesc(DateUtils.chineseDate(DateUtil.date()));
		// 封装补充故障原因
		List<String> faultReasonItemNames = new ArrayList<>();
		if (StringUtil.isNotBlank(malfunctionWork.getFaultReasonItem())) {
			List<String> faultReasonItems = Func.toStrList(malfunctionWork.getFaultReasonItem());
			for (String reasonItem : faultReasonItems) {
				String problemName = DictCache.getValue("fault_reason", reasonItem);
				faultReasonItemNames.add(problemName);
			}
		}
		robotContentDTO.setMalfunctionDesc(Func.isEmpty(faultReasonItemNames) ? "" : faultReasonItemNames.stream().collect(Collectors.joining("、")));
		robotContentDTO.setMaintainImgUrl("https://erised.oss-cn-shenzhen.aliyuncs.com/img/202309041654060.jpg");
		robotUtil.sendRobotMessage(RequestContextHolder.getRequestAttributes(), planContent.getElevatorId(), planContent.getId(), robotContentDTO);
		// 给飞书推送表格更新
		if ("592800".equals(AuthUtil.getTenantId())) {
			asyncHttpUtil.createPost(projectApiConfiguration.getWeb() + "/admin/lark/galaxy/elevator/repair/plan", Func.toJson(planContent), WebUtil.getRequest());
		}
		return Boolean.TRUE;
	}

	@MsgNotice(businessType = BusinessType.REPAIR, node = TriggerNodeEnum.ASSIGN, parameterName = "repairWorkVO.planId")
	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean malfunctionWorkUpdate(RepairWorkVO repairWorkVO) {

		MaintainPlanContent maintainPlanContent = maintainPlanContentService.getById(repairWorkVO.getPlanId());
		if (Func.isEmpty(maintainPlanContent)) {
			throw new ServiceException("未找到对应工单!");
		}
		//计算维修达到时间
		Long buildingId = elevatorService.getById(repairWorkVO.getElevatorId()).getBuildingId();
		BuildingExt buildingExt = buildingExtService.getOne(Wrappers.<BuildingExt>lambdaQuery().eq(BuildingExt::getBuildingId, buildingId));
		if (StrUtil.isNotEmpty(buildingExt.getMalfunctionWorkArrivalTime())) {
			//预计达到时间
			long timeMillis = System.currentTimeMillis();
			if (buildingExt.getMalfunctionWorkArrivalTime().contains("m")) {
				Long time = Convert.toLong(buildingExt.getMalfunctionWorkArrivalTime().replace("m", "")) * 60 * 1000;
				timeMillis = timeMillis + time;
				Date date2 = new Date(timeMillis);
				repairWorkVO.setPlanArriveDate(date2);
			} else if (buildingExt.getMalfunctionWorkArrivalTime().contains("h")) {
				Long time = Convert.toLong(buildingExt.getMalfunctionWorkArrivalTime().replace("h", "")) * 60 * 60 * 1000;
				timeMillis = timeMillis + time;
				Date date2 = new Date(timeMillis);
				repairWorkVO.setPlanArriveDate(date2);
			}
		}

		maintainPlanContentUserService.saveBatch(maintainPlanContent.getId(), repairWorkVO.getUserIds(), repairWorkVO.getPlanArriveDate());
		ElevatorSimpleInfoVO elevatorInfo = maintainPlanContentService.getElevatorSimpleInfo(repairWorkVO.getPlanId());

		Date date = new Date();
		List<String> userName = new ArrayList<>();
		for (Long userId : repairWorkVO.getUserIds()) {
			SimpleUserVO assignUserInfo = userService.getSimpleUserInfo(userId);
			if (Func.isNotEmpty(assignUserInfo)) {
//				if (Func.isNotEmpty(assignUserInfo.getOpenid())) {
//					MaintainMalfunctionWork maintainMalfunctionWork = this.getOne(Wrappers.<MaintainMalfunctionWork>lambdaQuery().eq(MaintainMalfunctionWork::getPlanId, maintainPlanContent.getId()), false);
//					log.info("===========给维修发送模板消息,维修人:[{}]===========", assignUserInfo.getUserName());
//					Map<String, String> templateDataMap = new HashMap<>(8);
//					templateDataMap.put("first", "您好，您有新的维修任务!");
//					templateDataMap.put("keyword1", maintainMalfunctionWork == null ? null : maintainMalfunctionWork.getName());
//					templateDataMap.put("keyword2", maintainMalfunctionWork == null ? null : maintainMalfunctionWork.getPhone());
//					templateDataMap.put("keyword3", DateUtil.format(date, DatePattern.NORM_DATETIME_MINUTE_PATTERN));
//					templateDataMap.put("keyword4", maintainMalfunctionWork == null ? null : maintainMalfunctionWork.getMfDesc());
//					templateDataMap.put("remark", "请及时登录梯无忧小程序执行维修任务!");
//					weChatDialogueService.sendMsg(assignUserInfo.getOpenid(), TemplateMsgConstant.T_REPAIR_TASK_ID, templateDataMap);
//				}
//
//				log.info("===========给维修人发送手机短信,维修人:[{}], 手机号码:[{}]===========", assignUserInfo.getUserName(), assignUserInfo.getPhone());
//				Map<String, String> smsParam = new HashMap<>(2);
//				smsParam.put("auditStatus", "【待开始】");
//				SmsUtil.sendMessage(MaintenanceSmsConstant.MAINTENANCE_PEOPLE, BladeConstant.ADMIN_TENANT_ID, smsParam, assignUserInfo.getPhone());
//
//				log.info("===========给维修人打电话,审批人:[{}], 手机号码:[{}]===========", assignUserInfo.getUserName(), assignUserInfo.getPhone());
//				Map<String, String> phoneMap = new HashMap<>(4);
//				phoneMap.put("place", elevatorInfo.getBuildingName() + elevatorInfo.getElevatorAddress());
//				phoneMap.put("phone", assignUserInfo.getPhone());
//				phoneMap.put("templateCode", VoiceConstant.MAINTENANCE_ADD_USER);
//				HttpUtil.createPost(projectApiConfiguration.getWeb() + "/admin/voice/sendPhone").body(JSONObject.toJSONString(phoneMap)).execute().body();

				userName.add(assignUserInfo.getUserName());
			}
		}

		// 更新分配时间与分配次数
		MaintainPlanContentExt maintainPlanContentExt = maintainPlanContentExtService.getOne(Wrappers.<MaintainPlanContentExt>lambdaQuery().eq(MaintainPlanContentExt::getPlanId, repairWorkVO.getPlanId()), false);
		if (Func.isEmpty(maintainPlanContentExt)) {
			throw new ServiceException("数据异常！");
		}
		if (maintainPlanContentExt.getAssignmentCounts() == 0) {
			Date now = new Date();
			maintainPlanContentExt.setAllocateTime(now);
			long allocateDuration = now.getTime() - maintainPlanContent.getCreateTime().getTime();
			maintainPlanContentExt.setAllocateDuration(allocateDuration < 0 ? 0 : allocateDuration);
		}
		maintainPlanContentExt.setAssignmentCounts(maintainPlanContentExt.getAssignmentCounts() + 1);
		maintainPlanContentExt.setTransferUserFlag(1);
		boolean tsFlag = roleService.hasRole(repairWorkVO.getUserIds(), BaseRoleConstant.TECHNICAL_SUPPORT);
		if (tsFlag) {
			maintainPlanContentExt.setApplyTsFlag(1);
		}
		boolean peFlag = roleService.hasRole(repairWorkVO.getUserIds(), BaseRoleConstant.EXPERT);
		if (peFlag) {
			maintainPlanContentExt.setApplyPeFlag(1);
		}
		maintainPlanContentExtService.updateById(maintainPlanContentExt);

		// 插入任务跟踪信息
		PlanLogDTO planLogDTO = new PlanLogDTO();
		planLogDTO.setPlanUser(String.join(",", userName));
		malfunctionLogService.insertWorkLog(maintainPlanContent.getId(), WorkTrackStatusEnum.WORK_USER.getTypeName(), maintainPlanContent.getStatus(), JSONObject.toJSONString(planLogDTO));

		// 给飞书推送表格更新
		if ("592800".equals(AuthUtil.getTenantId())) {
			asyncHttpUtil.createPost(projectApiConfiguration.getWeb() + "/admin/lark/galaxy/elevator/repair/plan", Func.toJson(maintainPlanContent), WebUtil.getRequest());
		}

		this.sendYjMsg(repairWorkVO, repairWorkVO.getPlanId());
		return true;
	}

	/**
	 * 更改电梯状态
	 *
	 * @param elevatorId
	 */
	private void updateEleStatus(Long elevatorId, Long planId, Integer isStop, Integer planStatus) {
		Elevator elevator = elevatorService.getById(elevatorId);
		if (elevator == null) {
			throw new ServiceException("电梯不存在！");
		}
		// 改状态
		elevator.setIsStop(isStop);
		if (elevatorService.updateById(elevator)) {
			ElevatorPlanStatus elevatorPlanStatus = elevatorPlanStatusService.getOne(Wrappers.<ElevatorPlanStatus>lambdaQuery().eq(ElevatorPlanStatus::getElevatorId, elevatorId), false);
			if (elevatorPlanStatus != null) {
				elevatorPlanStatus.setPlanStatus(planStatus);
				elevatorPlanStatus.setPlanId(planId);
				// 若为停梯状态，故障统计+1
				if (isStop == ElevatorStatusEnum.STOP.getStatus()) {
					elevatorPlanStatus.setCounts(elevatorPlanStatus.getCounts() + 1);
				}
				elevatorPlanStatusService.updateById(elevatorPlanStatus);
			}
		}
	}

	private List<MaintainParts> recursionPart(Long id, Map<Long, List<MaintainParts>> listMap, List<MaintainParts> list) {
		if (id == 0) {
			return list;
		}
		MaintainParts maintainParts = listMap.get(id).get(0);
		list.add(maintainParts);
		if (maintainParts.getParentId() != 0L) {
			recursionPart(maintainParts.getParentId(), listMap, list);
		}
		return list;
	}
}


